/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.ucuenca.ec.nosql.conexion;

import edu.ucuenca.ec.nosql.controller.util.TipoNodo;
import edu.ucuenca.ec.nosql.modelos.Persona;
import edu.ucuenca.ec.nosql.controller.util.TipoRelacion;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.cypher.javacompat.ExecutionResult;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.Transaction;
import org.neo4j.helpers.collection.IteratorUtil;

/**
 *
 * @author mivkys
 */
public class Neo4jEngine {

    private static GraphDatabaseService db;

    public static void conexionFactory() {
        GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
        shudownConexion();
        db = dbFactory.newEmbeddedDatabase("/Users/mivkys/Documents/test");

    }

    public static void crearVariosNodos(List<Persona> amigos) {
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                for (Persona arg : amigos) {
                    Node javaNode = db.createNode(TipoNodo.USUARIO);
                    javaNode.setProperty("Id", arg.getId());
                    //javaNode.setProperty("username", arg.getUsername());
                    javaNode.setProperty("nombres", arg.getNombres());
                    javaNode.setProperty("pass", arg.getPass());
                    //nodes.add(javaNode);
                    tx.success();
                }
            }
        }
    }

    public static void crearUnNodo(Persona amigo) {
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                Node javaNode = db.createNode(TipoNodo.USUARIO);

                javaNode.setProperty("Id", amigo.getId());
                //javaNode.setProperty("username", amigo.getUsername());
                javaNode.setProperty("nombres", amigo.getNombres());
                javaNode.setProperty("pass", amigo.getPass());
                tx.success();
            }
        }
    }

    public static void crearRelacion(Persona persona, Persona amigo) {
        if (!persona.equals(amigo)) {
            ExecutionEngine engine = new ExecutionEngine(db);
            ExecutionResult result;
            if (db != null) {
                try (Transaction txr = db.beginTx()) {
                    String querry = "MATCH (a),(b)\n"
                            + "WHERE a.Id =" + persona.getId() + " AND b.Id =" + amigo.getId() + "\n"
                            + "CREATE (a)-[r:" + TipoRelacion.AMIGOS.name() + "{ Id :" + amigo.getId() + " }]->(b)\n"
                            + "RETURN r";
                    result = engine.execute(querry);
                    txr.success();
                }
            }
        }
    }

    public static void crearRelaciones(Persona persona, List<Persona> amigos) {
        ExecutionEngine engine = new ExecutionEngine(db);
        ExecutionResult result;
        if (db != null) {
            try (Transaction txr = db.beginTx()) {
                for (Persona amigo : amigos) {
                    String querry = "MATCH (a),(b)\n"
                            + "WHERE a.Id =" + persona.getId() + " AND b.Id =" + amigo.getId() + "\n"
                            + "CREATE (a)-[r:" + TipoRelacion.AMIGOS.name() + "{ Id :" + amigo.getId() + " }]->(b)\n"
                            + "RETURN r";
                    result = engine.execute(querry);
                }
                txr.success();
            }
        }
    }

//    public static List<Node> buscaRelaciones(Persona amigo) {
//        List<Node> nodes = new ArrayList<>();
//        ExecutionEngine engine = new ExecutionEngine(db);
//        ExecutionResult result;
//        try (Transaction ignored = db.beginTx()) {
//            String querry = "match (n {Id:" + amigo.getId() + "})--return n.name";
//            result = engine.execute(querry);
//            Iterator<Node> n_column = result.columnAs("n");
//            for (Node node : IteratorUtil.asIterable(n_column)) {
//                int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
//
//                nodes.add(node);
//
//            }
//            ignored.success();
//        }
//        return nodes;
//    }
    public static List<Persona> matchAlgunosNodos(List<Persona> amigos) {////muy costoso la consulta
        List<Persona> personas = new ArrayList<>();
        ExecutionEngine engine = new ExecutionEngine(db);
        ExecutionResult result;
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                for (Persona amigo : amigos) {
                    String querry = "match (n {Id:" + amigo.getId() + "}) return n, n.name";
                    result = engine.execute(querry);
                    Iterator<Node> n_column = result.columnAs("n");
                    for (Node node : IteratorUtil.asIterable(n_column)) {
                        int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
                        if (id == amigo.getId()) {
                            personas.add(amigo);
                        }
                    }
                }
                tx.success();
            }
        }
        return (!personas.isEmpty()) ? personas : null;
    }

    public static List<Persona> matchAmigos(Persona usuario) {
        List<Persona> amigos = new ArrayList<>();
        ExecutionEngine engine = new ExecutionEngine(db);
        ExecutionResult result;
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                String querry = "MATCH (d {Id:" + usuario.getId() + "})<-[r:AMIGOS]->(n) RETURN n LIMIT 50";
                result = engine.execute(querry);
                Iterator<Node> n_column = result.columnAs("n");
                for (Node node : IteratorUtil.asIterable(n_column)) {
                    int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
                    String username = String.valueOf(node.getProperty("nombres"));
                    String nombres = String.valueOf(node.getProperty("nombres"));
                    String pass = String.valueOf(node.getProperty("pass"));
                    Persona amigo = new Persona(id, nombres, username, pass);
                    amigos.add(amigo);
                }
                tx.success();
            }
        }
        return (!amigos.isEmpty()) ? amigos : null;
    }

    public static Persona Loger(String user, String pass) {
        Persona usuario = null;
        if (db != null) {

            ExecutionEngine engine = new ExecutionEngine(db);
            ExecutionResult result;
            if (db != null) {
                try (Transaction tx = db.beginTx()) {
                    String querry = "MATCH (n:" + TipoNodo.USUARIO.name() + "{ nombres:\"" + user + "\",pass:\"" + pass + "\" }) RETURN n LIMIT 1";
                    result = engine.execute(querry);
                    Iterator<Node> n_column = result.columnAs("n");
                    for (Node node : IteratorUtil.asIterable(n_column)) {
                        int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
                        String username = String.valueOf(node.getProperty("nombres"));
                        String nombres = String.valueOf(node.getProperty("nombres"));
                        String passw = String.valueOf(node.getProperty("pass"));
                        usuario = new Persona(id, nombres, username, passw);
                    }
                    tx.success();
                }
            }
        } else {
            System.out.println("No hay conexion loger");
        }
        return usuario;
    }
//matchUnNodo
   public static Persona matchUnNodo(int id) {
        Persona usuario = null;
        if (db != null) {

            ExecutionEngine engine = new ExecutionEngine(db);
            ExecutionResult result;
            if (db != null) {
                try (Transaction tx = db.beginTx()) {
                    String querry = "MATCH (n:" + TipoNodo.USUARIO.name() + "{ Id:" + id  + " }) RETURN n LIMIT 1";
                    result = engine.execute(querry);
                    Iterator<Node> n_column = result.columnAs("n");
                    for (Node node : IteratorUtil.asIterable(n_column)) {
                        int idr = Integer.valueOf(String.valueOf(node.getProperty("Id")));
                        String username = String.valueOf(node.getProperty("nombres"));
                        String nombres = String.valueOf(node.getProperty("nombres"));
                        String passw = String.valueOf(node.getProperty("pass"));
                        usuario = new Persona(idr, nombres, username, passw);
                    }
                    tx.success();
                }
            }
        } else {
            System.out.println("No hay conexion loger");
        }
        return usuario;
    }

//    public static Persona convertNodo(Node node, List<Persona> personas) {
//        int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
//        for (Persona persona : personas) {
//            if (persona.getId() == id) {
//                return persona;
//            }
//        }
//        return null;
//    }
//
//    public static List<Persona> convertAllNodo(List<Node> nodes, List<Persona> personas) {
//        List<Persona> amigos = new ArrayList<>();
//        for (Node node : nodes) {
//            int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
//            for (Persona persona : personas) {
//                if (persona.getId() == id) {
//                    amigos.add(persona);
//                    System.out.println("Amigo:" + persona.getNombres());
//                }
//            }
//        }
//
//        return (!amigos.isEmpty()) ? amigos : null;
//    }
    public static List<Persona> matchAllNodos(int limite) {
        List<Persona> usuario = new ArrayList<>();
        ExecutionEngine engine = new ExecutionEngine(db);
        ExecutionResult result;
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                result = engine.execute("MATCH (n) RETURN n LIMIT " + limite + "");
                Iterator<Node> n_column = result.columnAs("n");
                for (Node node : IteratorUtil.asIterable(n_column)) {
                    int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
                    String username = String.valueOf(node.getProperty("nombres"));
                    String nombres = String.valueOf(node.getProperty("nombres"));
                    String pass = String.valueOf(node.getProperty("pass"));
                    Persona amigo = new Persona(id, nombres, username, pass);
                    usuario.add(amigo);
                }
                tx.success();
            }
        }
        return (!usuario.isEmpty()) ? usuario : null;
    }

    public static void shudownConexion() {
        if (db != null) {
            db.shutdown();
        }
    }
}
